%%%%%%%%%%%%%%%%%%%%%%%
%%
%% Module summary
%%
%% Main authors: Peter
%% Progress to usefulness:
%%
%% Mesh worker only performs lookups
%% end then dies, hail to parallelism!
%%
%%%%%%%%%%%%%%%%%%%%%%%

-module(mesh_worker).
-behaviour(gen_server).
-include("db.hrl").

-export([start_link/0,start_link/1]).
-export([init/1, handle_call/3,handle_cast/2,handle_info/2
        ,code_change/3,terminate/2]).


start_link() ->
    %io:format("Starting Mesh Worker\n"),
    gen_server:start_link(?MODULE,[],[]).

start_link(Args) ->
    %io:format("Starting Mesh Worker\n"),
    gen_server:start_link(?MODULE,Args,[]).
%
% Nodes are stored in an ordered set as tuples
% containing {hashed nodename, nodename}
%
init(State) ->
    {ok, State}.


handle_cast({lookup, Id, Caller}, State) ->
    %% Find node
    Dest = find_responsible_node(Id, State),
    %% And reply to caller, by using gen_server:reply,
    %% the caller thinks he made a synchronous call
    gen_server:reply(Caller, Dest),
    {stop, normal, State}.

% Unused functions atm
handle_call(_Msg,_From, State) ->
    {noreply, State}.
%
% Function called when terminated
%
terminate(normal,_State) ->
    ok;
terminate(_Reason,_State) ->
    io:format("Terminating Mesh worker~n").

handle_info(Info, State) ->
    io:format("Received info message: ~w~n", Info),
    {noreply ,State}.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.




% % % % % % % % % % % % % % % % % % % % % %
%    Helper functions                     %
% % % % % % % % % % % % % % % % % % % % % % 

%
% Given a value (Node or Key), find
% the responsible node

find_responsible_node(Value, State) ->
    Nodes = State#mesh.nodes,
    ValueHash = hash:hash(Value),
    List = ordsets:to_list(Nodes),
    List2 = lists:dropwhile(fun({NodeHash,_}) -> NodeHash < ValueHash end,List),
    case length(List2) of
        0 -> element(2,lists:nth(1,List));
        _ -> element(2,lists:nth(1,List2))
    end.

